package org.dei.perla.sys.console;



import java.net.Socket;

import org.dei.perla.parser.statements.Query;
import org.dei.perla.sys.console.messages.ConsoleMessage.PerLaRequest;
import org.dei.perla.sys.console.ConsoleUtils;
import org.dei.perla.sys.core.QueryParserStatic;
import org.dei.perla.utils.pipe.Pipe;

/**
 * Per ogni richiesta di connessione viene generato un Thread
 * rappresentato da questa classe.
 * @author diego
 */
class ServerThread extends Thread {

	/**
	 * Il socket che verra' usato per la connessione
	 */
	private Socket pSocket;
	
	private Pipe<String> queryToInjectPipe;
	
	/**
	 * Costruttore
	 * @param parSocket
	 */
	ServerThread(Socket parSocket) {
		this.pSocket = parSocket;
		this.queryToInjectPipe = new Pipe<String>("queryToParse");
	}
	
	public Pipe<String> getQueryToInjectPipe() {
		return queryToInjectPipe;
	}

	/**
	 * Metodo per far partire l'attivita' 
	 */
	public void run() {
		
		boolean tConnectionOpened = true;
		
		try {
			
			//...fino a quando non arriva il segnale di connessione da terminare...
			while (tConnectionOpened) {					
				
				//...Ricevo la richiesta...
				PerLaRequest tRequest = ConsoleUtils.receiveRequest(pSocket);				
								
				System.out.println("Controllo integrita' \n");
				
				if (!tRequest.isInitialized()) {
				 System.out.println("Errore nel messaggio \n");
				 }else {System.out.println("Il messaggio e' OK \n");}

				//Recupero l'header e agisco di conseguenza
				switch (tRequest.getRequestHeader()) {
					case TEST_QUERY : {
						String query = tRequest.getInjectQueryRequestMessage().getQueryToInject();
						if( QueryParserStatic.isValid(query) == false){
							ConsoleUtils.injectCommandResponse(this.pSocket, "error parsing query");
						}
						else{
							ConsoleUtils.injectCommandResponse(this.pSocket, "parsing query success");
						}
						break;
					}
					case STOP_QUERY : {
						tConnectionOpened = false;			
						break;
					}
					case SHOW_VERSION : {
						ConsoleUtils.versionCommandResponse(this.pSocket);
						break;
					}
					case INSPECT_COMMAND:{
						System.out.println("Received INSPECT_COMMAND");
						ConsoleUtils.inspectResponse(this.pSocket, tRequest.getInspectRequestMessage().getAgentId());
						break;
					}
					case INJECT_QUERY : {
						String query = tRequest.getInjectQueryRequestMessage().getQueryToInject();
						Query parsedQuery = QueryParserStatic.parse(query);
						
						if(parsedQuery == null){
							ConsoleUtils.injectCommandResponse(this.pSocket, "error parsing query");
						}
						else{
							//QueryParserStatic.enqueueResult(parsedQuery);
							ConsoleUtils.injectCommandResponse(this.pSocket, "parsing query success");
						}
						break;
					}
					default:{
						break;
					}
				}
				
				//..controllo che il client non abbia chiuso la connessione, altrimenti termino			
				if (!this.pSocket.isConnected()) tConnectionOpened = false;	
			}
	
		} catch (Exception e) {
			System.out.println("Errore nel server");
			e.printStackTrace();
		}
		
		//...qui la connessione e' stata chiusa, agisco di conseguenza.
		try {
			this.finalize();		
		} catch (Throwable e) {
			System.out.println("Errore nella chiusura del server...\n");		
		}
		System.out.println("Questo ServerThread ha terminato, addio....\n");
		
	}
}
